<?php
//-------------------------------------------------------------------------
// OVIDENTIA http://www.ovidentia.org
// Ovidentia is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//-------------------------------------------------------------------------
/**
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
 * @copyright Copyright (c) 2006 by CANTICO ({@link http://www.cantico.fr})
 */
include_once 'base.php';
require_once $GLOBALS['babInstallPath'] . '/addons/widgets/widgets/gauge.class.php';


/**
 * Constructs a Widget_ProgressBar.
 *
 * @param string		$id			The item unique id.
 * @return Widget_ProgressBar
 */
function Widget_ProgressBar($id = null)
{
	return new Widget_ProgressBar($id);
}


/**
 * A Widget_ProgressBar is a widget that display a dynamic gauge
 */
class Widget_ProgressBar extends Widget_Gauge implements Widget_Displayable_Interface 
{
	
	
	private $progressAction = null;
	
	
	/**
	 * @var int
	 */
	private $available_memory = 0;
	
	/**
	 * @see Widget_ProgressBar::displayMemoryUsage()
	 * @var bool
	 */
	private $display_memory = true;
	
	
	/**
	 * @param string $id			The item unique id.
	 * @return Widget_ProgressBar
	 */
	public function __construct($id = null)
	{
		parent::__construct($id);
		
		
	}
	
	
	
	private function return_bytes($val) {

		
	    $val = trim($val);
	    $last = strtolower($val[strlen($val)-1]);
	   
	    switch($last) {

	        case 'g':
	            $val *= 1024;
	        case 'm':
	            $val *= 1024;
	        case 'k':
	            $val *= 1024;
	    }
	
	    return $val;
	}
	
	


	/**
	 * the progress action link to a page used to update the gauge progression status
	 * the page used beind this action will trigger multiples calls of the method updateProgress to dynamicaly update the progress bar
	 * 
	 * @see Widget_ProgressBar::updateProgress()
	 * 
	 * @param	string	$title
	 * @return	Widget_ProgressBar
	 */
	public function setProgressAction(Widget_Action $action)
	{
		$action->setParameter('widget_id', $this->getId());
		
		$this->progressAction = $action;
		return $this;
	}
	
	
	
	/**
	 * Action to trigger on complete progression (100%)
	 * if no button supplied, the page will change automatically where the progress bar reach its maximum
	 * 
	 * @param	Widget_Action			$action
	 * @param	Widget_Button | null	$button		Optional button used to trigger the action
	 * 
	 * @return Widget_ProgressBar
	 */ 
	public function setCompletedAction(Widget_Action $action, $button = null)
	{
		$this->setMetadata('completedAction', $action->url());
		
		if (null !== $button) {
			assert('$button instanceOf Widget_Button; /* The "button" parameter must be instanceOf Widget_Button. */');
			$this->setMetadata('completedButton', $button->getId());
			
			$button->disable();
		}
		
		return $this;
	}
	
	
	/**
	 * Display memory usage in percentage behind the progress bar
	 * to allocate more memory, use ini_set('memory_limit', X) before updating progress
	 * 
	 * @param	bool	$display
	 * 
	 * @return Widget_ProgressBar
	 */
	public function displayMemoryUsage($display = true)
	{
		$this->display_memory = $display;
		return $this;
	}
	
	
	
	/**
	 * This method is used behind the action set with setProgressAction
	 * the title have to be initialized with the setTitle method
	 * the progression have to be initialized with the setProgress method
	 * 
	 * @param	int		$progress	percentage
	 * @param	string	$title		to dynamicaly update the title
	 * 
	 * @return Widget_ProgressBar
	 */ 
	public function updateProgress($progress, $title = null)
	{
		static $init = null;
		static $lastvalue = null;
		
		$progress = round($progress);
		
		if ($lastvalue === array($progress, $title)) {
			// do nothing if progress or message are not modified
			return $this;
		}
		
		$lastvalue = array($progress, $title);

		
		if (null === $init) {
			
			$this->available_memory = $this->return_bytes(ini_get('memory_limit'));
			
			
			
			if (function_exists('apache_setenv')) {
				@apache_setenv('no-gzip'			, 1);
			}
			@ini_set('zlib.output_compression'	, 0);
			@ini_set('implicit_flush'			, 1);
			for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
			ob_implicit_flush(1);
			
			echo '<html><head></head><body style="background:#fff;">'."\n";
			
			$init = true;
		}
		
		
		$widget_id = bab_rp('widget_id');
		
		if (null === $title) {
			$title = 'null';
		} else {
			$title = "'".bab_toHtml($title, BAB_HTML_JS)."'";
		}
		
		
		$mem = memory_get_usage();
		$percent_mem = ceil(($mem * 100) / $this->available_memory);
		
		echo sprintf('<script type="text/javascript">
		//<![CDATA[
			window.parent.babAddonWidgets.progressBar(\'%s\', %s, %s, %d);
		//]]>
		</script>', $widget_id, $progress, $title, $percent_mem);
		
				
		return $this;
	}
	
	
	/**
	 * While the bar is in progress, the button to go to the completed action is locked, the button is unlocked automaticaly at progress 100%, in case of error, this method unlock the button to go next step without moving progress
	 * 
	 * @param	string 	$title	optional title to update
	 * 
	 * @return Widget_ProgressBar
	 */
	public function unlock($title = null)
	{
		if (null === $title) {
			$title = 'null';
		} else {
			$title = "'".bab_toHtml($title, BAB_HTML_JS)."'";
		}
		
		$widget_id = bab_rp('widget_id');
		
		echo sprintf('<script type="text/javascript">
		//<![CDATA[
			window.parent.babAddonWidgets.progressBarUnlock(\'%s\', %s);
		//]]>
		</script>', $widget_id, $title);
		
		return $this;
	}


	public function getClasses()
	{
		$classes = parent::getClasses();
		$classes[count($classes) - 1] = 'widget-progressbar';
		return $classes;
	}
	


	public function display(Widget_Canvas $canvas)
	{	
		$iframeOptions = $this->Options();
		$iframeOptions->width(10,'px');
		$iframeOptions->height(10,'px');
		
		$content = array();
		
		$title = $this->getTitle();
		
		if ($title) {
			$content[] = $canvas->div($this->getId().'_title', array(), array($canvas->text($title)));
		}
		
		$content[] = parent::gauge($canvas, $this->getId().'_gauge', parent::getClasses());
		
		if ($this->display_memory) {
			$content[] = $canvas->div(null, array('widget-progressbar-memory'), array(
				$canvas->span(null, array(), array($canvas->text(widget_translate('Memory usage').' : '))),
				$canvas->span($this->getId().'_memory', array(), array('???')),
				$canvas->span(null, array(), array('%'))
			));
		}
		
		$content[] = $canvas->iframe('', $this->progressAction->url(), $iframeOptions);
		
		return $canvas->vbox(
			$this->getId(),
			$this->getClasses(),
			$content
		)
		.$canvas->metadata(
			$this->getId(), 
			$this->getMetadata()
		);
	}

}
